/////////////////////////////////////////////////////////////////////////
//
// Amuse Engine - graphics
// Copyright (c) 2015.  All Rights Reserved
//
// File:		AEColor.inl
// Author:		Gianluca Belardelli
// Date:		15/06/2015
//
/////////////////////////////////////////////////////////////////////////
#ifndef _AECOLOR_INL_
#define _AECOLOR_INL_

AE_FORCEINLINE AEColor::AEColor( void )
{
	uiColorValue=0;
}

AE_FORCEINLINE AEColor::AEColor( AEUINT8 uiRed, AEUINT8 uiGreen, AEUINT8 uiBlue, AEUINT8 uiAlpha )
{
	this->uiRed=uiRed;
	this->uiGreen=uiGreen;
	this->uiBlue=uiBlue;
	this->uiAlpha=uiAlpha;
}

AE_FORCEINLINE AEColor::AEColor( AEBOOL32 bUninitialized )
{
}

AE_FORCEINLINE void AEColor::Clear( void )
{
	uiColorValue=0;
}

AE_FORCEINLINE void AEColor::SetNoAlpha( AEColor colColor )
{
	uiRed=colColor.uiRed;
	uiGreen=colColor.uiGreen;
	uiBlue=colColor.uiBlue;
}

AE_FORCEINLINE void AEColor::ToFloat( AEVector3f &vcDest ) const
{
	RGB_To_Float( *this, vcDest );
}

AE_FORCEINLINE AEVector3f AEColor::ToFloat( void ) const
{
	AEVector3f vcColor;
	RGB_To_Float( *this, vcColor );
	return vcColor;
}

AE_FORCEINLINE void AEColor::ToFloat4( AEVector4f &vcDest ) const
{
	RGBA_To_Float( *this, vcDest );
}

AE_FORCEINLINE const AEVector4f AEColor::ToFloat4( void ) const
{
	AEVector4f vcColor;
	RGBA_To_Float( *this, vcColor );
	return vcColor;
}

AE_FORCEINLINE void AEColor::FromFloat( const AEVector3f &vcColor )
{
	*this = Float_To_RGB( vcColor );
}

AE_FORCEINLINE void AEColor::FromFloat4( const AEVector4f &vcColor )
{
	*this = Float_To_RGBA( vcColor );
}

AE_FORCEINLINE void AEColor::SetRGBA( AEUINT32 uiRed, AEUINT32 uiGreen, AEUINT32 uiBlue, AEUINT32 uiAlpha )
{
	this->uiRed=uiRed;
	this->uiGreen=uiGreen;
	this->uiBlue=uiBlue;
	this->uiAlpha=uiAlpha;
}

AE_FORCEINLINE void AEColor::SetRGB( AEUINT32 uiRed, AEUINT32 uiGreen, AEUINT32 uiBlue )
{
	this->uiRed=uiRed;
	this->uiGreen=uiGreen;
	this->uiBlue=uiBlue;
}

AE_FORCEINLINE AEUINT32 AEColor::GetRGBA( void ) const
{
	return (AEUINT32)((AEUINT32)((AEUINT32)uiRed) + (((AEUINT32)((AEUINT32)uiGreen)) << 8) + (((AEUINT32)((AEUINT32)uiBlue))<<16) + (((AEUINT32)((AEUINT32)uiAlpha))<<24));
}

AE_FORCEINLINE void AEColor::SetRGBA( AEUINT32 uiRGBA )
{
	uiRed = ((uiRGBA)&0xFF);
	uiGreen = ((uiRGBA>>8)&0xFF);
	uiBlue = ((uiRGBA>>16)&0xFF);
	uiAlpha = ((uiRGBA>>24)&0xFF);
}

AE_FORCEINLINE AEUINT32 AEColor::GetNative( void ) const
{
	return uiColorValue;
}

AE_FORCEINLINE AEVector4f AEColor::GetAsVec4( void ) const
{
	AEVector4f retVal;
	RGBA_To_Float( *this, retVal );
	return retVal;
}

AE_FORCEINLINE AEColor &AEColor::operator = ( const AEColor &other )
{
	uiColorValue=other.uiColorValue;
	return *this;
}

AE_FORCEINLINE AEColor &AEColor::operator = ( const AEVector3f &other )
{
	*this = Float_To_RGB(other);
	return *this;
}

AE_FORCEINLINE AEBOOL32 AEColor::operator == ( const AEColor &other ) const
{
	return uiColorValue == other.uiColorValue;
}

AE_FORCEINLINE AEBOOL32 AEColor::operator != ( const AEColor &other ) const
{
	return uiColorValue != other.uiColorValue;
}

AE_FORCEINLINE void AEColor::operator += ( const AEColor &other )
{
	AEUINT32 uiRes;
	uiRes = uiRed + other.uiRed;
	if( uiRes > 255 )
		uiRes=255;
		
	uiRed=(AEUINT8)uiRes;
	
	uiRes = uiGreen + other.uiGreen;
	if( uiRes > 255 )
		uiRes=255;
	
	uiGreen=(AEUINT8)uiRes;
	
	uiRes = uiBlue + other.uiBlue;
	if( uiRes > 255 )
		uiRes=255;
	
	uiBlue=(AEUINT8)uiRes;
	
	uiRes = uiAlpha + other.uiAlpha;
	if( uiRes > 255 )
		uiRes=255;
	
	uiAlpha=(AEUINT8)uiRes;
}

AE_FORCEINLINE void AEColor::operator -= ( const AEColor &other )
{
	AEINT32 nRes;
	nRes = uiRed - other.uiRed;
	if( nRes < 0 )
		nRes=0;
	
	uiRed=(AEUINT8)nRes;
	
	nRes = uiGreen - other.uiGreen;
	if( nRes < 0 )
		nRes=0;
	
	uiGreen=(AEUINT8)nRes;
	
	nRes = uiBlue - other.uiBlue;
	if( nRes < 0 )
		nRes=0;
	
	uiBlue=(AEUINT8)nRes;
	
	nRes = uiAlpha - other.uiAlpha;
	if( nRes < 0 )
		nRes=0;
	
	uiAlpha=(AEUINT8)nRes;
}

AE_FORCEINLINE void AEColor::operator *= ( const AEColor &other )
{
	AEUINT32 uiRes;
	uiRes = (AEUINT32)uiRed * (AEUINT32)other.uiRed;
	uiRed=(AEUINT8)(uiRes / 255);
	
	uiRes = (AEUINT32)uiGreen * (AEUINT32)other.uiGreen;
	uiGreen=(AEUINT8)(uiRes / 255);
	
	uiRes = (AEUINT32)uiBlue * (AEUINT32)other.uiBlue;
	uiBlue=(AEUINT8)(uiRes / 255);
	
	uiRes = (AEUINT32)uiAlpha * (AEUINT32)other.uiAlpha;
	uiAlpha=(AEUINT8)(uiRes / 255);
}

AE_FORCEINLINE void AEColor::operator *= ( AEFLOAT32 fFactor )
{
	AEUINT32 uiRes;
	
	if( fFactor <0.f )
		fFactor=0.f;

	uiRes = (AEUINT32)((AEFLOAT32)uiRed*fFactor);
	if( uiRes > 255 )
		uiRes=255;
		
	uiRed=(AEUINT8)uiRes;

	
	uiRes = (AEUINT32)((AEFLOAT32)uiGreen*fFactor);
	if( uiRes > 255 )
		uiRes=255;
		
	uiGreen=(AEUINT8)uiRes;

	
	uiRes = (AEUINT32)((AEFLOAT32)uiBlue*fFactor);
	if( uiRes > 255 )
		uiRes=255;
		
	uiBlue=(AEUINT8)uiRes;

	
	uiRes = (AEUINT32)((AEFLOAT32)uiAlpha*fFactor);
	if( uiRes > 255 )
		uiRes=255;
		
	uiAlpha=(AEUINT8)uiRes;
}

AE_FORCEINLINE AEColor AEColor::operator+ ( const AEColor &other ) const
{
	AEColor colColor = *this;
	colColor += other;
	return colColor;
}

AE_FORCEINLINE AEColor AEColor::operator- ( const AEColor &other ) const
{
	AEColor colColor = *this;
	colColor -= other;
	return colColor;
}

AE_FORCEINLINE AEColor AEColor::operator* ( const AEColor &other ) const
{
	AEColor colColor = *this;
	colColor *= other;
	return colColor;
}

AE_FORCEINLINE AEColor AEColor::operator* ( AEFLOAT32 fFactor ) const
{
	AEColor colColor = *this;
	colColor *= fFactor;
	return colColor;
}
AE_FORCEINLINE AEBOOL32 AEColor::IsZero( void ) const
{
	return uiColorValue == 0;
}

AE_FORCEINLINE AEBOOL32 AEColor::IsBlack( void ) const
{
	return ( (uiRed == 0) && ( uiGreen == 0 ) && ( uiBlue == 0 ) );
}

AE_FORCEINLINE AEFLOAT32 AEColor::GetIntensity( void ) const
{
	return ( (AEFLOAT32)uiRed + (AEFLOAT32)uiGreen + (AEFLOAT32)uiBlue ) * AE_INTENSITYDIV;
}

AE_FORCEINLINE void AEColor::SetRandomColor( void )
{
	SetRGBA( rand()%255, rand()%255, rand()%255, rand()%255 );
}

AE_FORCEINLINE void AEColor::Lerp( const AEColor &colColor1, const AEColor &colColor2, AEFLOAT32 fFactor)
{
	if( fFactor < 0.f )
	  fFactor = 0.f; 
	else if( fFactor > 1.f)
		fFactor=1.f;

	AEFLOAT32 f2 = 1.f-fFactor;
	uiRed = (AEUINT8)( (AEFLOAT32)colColor1.uiRed * f2 + (AEFLOAT32)colColor2.uiRed * fFactor );
	uiGreen = (AEUINT8)( (AEFLOAT32)colColor1.uiGreen * f2 + (AEFLOAT32)colColor2.uiGreen * fFactor );
	uiBlue = (AEUINT8)( (AEFLOAT32)colColor1.uiBlue * f2 + (AEFLOAT32)colColor2.uiBlue * fFactor );
	uiAlpha = (AEUINT8)( (AEFLOAT32)colColor1.uiAlpha * f2 + (AEFLOAT32)colColor2.uiAlpha * fFactor );
}

AE_FORCEINLINE AEColor AEColor::Float_To_RGB( const AEVector3f &vcColor )
{
	AEColor colDest;
	
	AEINT32 uiRed = (AEINT32)( vcColor.GetComponent<0>().operator*(255.99f) );
	if( uiRed > 255 )
		colDest.uiRed = 255;
	else
		colDest.uiRed = uiRed;
	
	AEINT32 uiGreen = (AEINT32)( vcColor.GetComponent<1>().operator*(255.99f) );
	if( uiGreen > 255 )
		colDest.uiGreen=255;
	else
		colDest.uiGreen=uiGreen;

	AEINT32 uiBlue = (AEINT32)( vcColor.GetComponent<2>().operator*(255.99f) );
	if( uiBlue > 255 )
		colDest.uiBlue=255;
	else
		colDest.uiBlue=uiBlue;

	return colDest;
}

AE_FORCEINLINE AEColor AEColor::Float_To_RGBA( const AEVector4f &vcColor )
{
	AEColor colDest;
	
	AEINT32 uiRed = (AEINT32)( vcColor.GetComponent<0>().operator*(255.99f) );
	if( uiRed > 255 )
		colDest.uiRed = 255;
	else
		colDest.uiRed = uiRed;
	
	AEINT32 uiGreen = (AEINT32)( vcColor.GetComponent<1>().operator*(255.99f) );
	if( uiGreen > 255 )
		colDest.uiGreen=255;
	else
		colDest.uiGreen=uiGreen;

	AEINT32 uiBlue = (AEINT32)( vcColor.GetComponent<2>().operator*(255.99f) );
	if( uiBlue > 255 )
		colDest.uiBlue=255;
	else
		colDest.uiBlue=uiBlue;

	AEINT32 uiAlpha = (AEINT32)( vcColor.GetComponent<3>().operator*(255.99f) );
	if( uiAlpha > 255 )
		colDest.uiAlpha=255;
	else
		colDest.uiAlpha=uiAlpha;

	return colDest;
}

AE_FORCEINLINE void AEColor::RGB_To_Float( AEColor colColor, AEVector3f &vcDest )
{
	vcDest.Set( (AEFLOAT32)colColor.uiRed * AE_1DIV255, (AEFLOAT32)colColor.uiGreen * AE_1DIV255, (AEFLOAT32)colColor.uiBlue * AE_1DIV255 );
}

AE_FORCEINLINE void AEColor::RGBA_To_Float( AEColor colColor, AEVector4f &vcDest )
{
	vcDest.Set( (AEFLOAT32)colColor.uiRed * AE_1DIV255, (AEFLOAT32)colColor.uiGreen * AE_1DIV255, (AEFLOAT32)colColor.uiBlue * AE_1DIV255, (AEFLOAT32)colColor.uiAlpha * AE_1DIV255 );
}

#endif // _AECOLOR_INL_
